package chan.project.utils.routeTemplate;

import chan.project.model.dto.location.Coordinates;
import chan.project.model.entity.Location;
import chan.project.utils.DistanceCalculatorUtil;
import cn.hutool.json.JSONUtil;
import lombok.AllArgsConstructor;
import lombok.Data;

import java.util.ArrayList;
import java.util.List;

//todo 使用策略方法来修改所有的模板方法
public abstract class RouteTemplate {
    private static final int INF = Integer.MAX_VALUE; // 定义无穷大

    /**
     * 根据图获取最短路径(旅行商问题)
     * 默认实现暴力方法
     * @param graph
     * @return
     */
    public Result minRoute(int[][] graph) {
        return null;
    }

    /**
     * 根据地点获取无向图
     * @param locationList
     * @return
     */
    public int[][] getLocationGraph(List<Location> locationList){
        int size = locationList.size();
        int[][] grape = new int[size][size];

        for (int i = 0; i < size; i++) {
            for (int j = 0; j < i; j++) {
                Coordinates coordinates1 = JSONUtil.toBean(locationList.get(i).getCoordinates(), Coordinates.class);
                Coordinates coordinates2 = JSONUtil.toBean(locationList.get(j).getCoordinates(), Coordinates.class);
                double calculateDistance = DistanceCalculatorUtil.calculateDistance(coordinates1.getLatitude(), coordinates1.getLongitude(), coordinates2.getLatitude(), coordinates2.getLongitude());
                grape[i][j] = (int) calculateDistance;
                grape[j][i] = (int) calculateDistance;
            }
            grape[i][i] = 0;
        }
        return grape;
    }

    /**
     * 模板方法
     * @param locationList
     * @return
     */
    public List<Location> order(List<Location> locationList){
        //1.将地点转化为图
        int[][] locationGraph = getLocationGraph(locationList);
        //2.动态规划计算最短路径
        Result tsp = minRoute(locationGraph);
        //3.按照返回的path重新排序
        int[] path = tsp.path;
        List<Location> resultList = new ArrayList<>();
        for (int i : path) {
            resultList.add(locationList.get(i));
        }
        return resultList;
    }
    // 用于保存最终结果的类
    @AllArgsConstructor
    @Data
    class Result {
        int cost;
        int[] path;
    }
}
